use crate::{
    card_weight::CardWeight,
    round::Round,
    turn::{TurnHandPileState, TurnState},
    utils::Utils,
};

pub struct NilCheck;
impl NilCheck {
    pub fn need_attack_nil_as_following(
        game: &Round,
        hand_pile_state: &TurnHandPileState,
        turn_trick_state: &TurnState,
        card_weights: &mut Vec<CardWeight>,
    ) -> bool {
        let cur_turn = game.cur_turn();
        let winning_turn_card = cur_turn.winning_card();
        let winning_card = &winning_turn_card.card;
        let leading_card = cur_turn.leading_card();
        let suit = leading_card.card.suit;
        //opponent_player 是指对方bid nil的玩家
        let opponent_player = Self::get_bid_nil_opponent_player(game, turn_trick_state);
        if let Some(player_id) = opponent_player {
            let player = &game.seats[player_id];
            if player.id == turn_trick_state.pre_player_id {
                if player.id == winning_turn_card.seat_id {
                    //fix：如果需要reachbid  这里也可以跟一张小牌 没必要跟大的 对家肯定会破0  跟大的对方破0 会更多的机会增加对方bag
                    if turn_trick_state.team_bt_delta > 0 {
                        let has_add = Utils::compute_lower_rank_and_most_card_num(
                            &hand_pile_state,
                            card_weights,
                        );
                        if has_add {
                            return true
                        }
                    } else {
                        if let Some(card) = Utils::get_highest_but_less_than_win_card(
                            &winning_card,
                            &hand_pile_state.playable_pile,
                        ) {
                            CardWeight::add_card_x(card.get_number() as i16, &card, card_weights);
                            return true;
                        }
                    }
                }
            } else if !player.is_suit_voided(suit)
                && (!winning_card.is_trump_card() || leading_card.card.is_trump_card())
            {
                let pile = &hand_pile_state.pile_suit_group.get_suit_pocker_cards(suit);
                let pile2 = &turn_trick_state
                    .history_suit_piles
                    .get_suit_pocker_cards(suit);
                let num = 13 - pile.len() as i8 - pile2.len() as i8;
                if num < 0 {
                    return false;
                }
                if let Some(card2) = Utils::get_highest_but_less_than_win_card(winning_card, pile) {
                    if card2.get_number() < winning_card.get_number() {
                        let num2 = Utils::get_greeter_rank_but_hidden_card_nums(
                            winning_card,
                            &pile,
                            pile2,
                        );
                        let num3 = num2 as f32 / num as f32;
                        if num3 >= 0.3 {
                            CardWeight::add_card_x(card2.get_number() as i16, &card2, card_weights);
                            return true;
                        }
                    } else {
                        if let Some(card) = Utils::get_lowest_rank_card(&pile) {
                            let num4 =
                                Utils::get_greeter_rank_but_hidden_card_nums(card, &pile, pile2);
                            let num5 = num4 as f32 / num as f32;
                            if num5 >= 0.3 {
                                CardWeight::add_card_x(
                                    card.get_number() as i16,
                                    &card,
                                    card_weights,
                                );
                                return true;
                            }
                        }
                    }
                }
            }
        }
        false
    }

    pub fn need_attack_nil_as_last(
        game: &Round,
        hand_pile_state: &TurnHandPileState,
        turn_trick_state: &TurnState,
        card_weights: &mut Vec<CardWeight>,
    ) -> bool {
        let cur_turn = game.cur_turn();
        let winning_turn_card = cur_turn.winning_card();
        let winning_card = &winning_turn_card.card;
        let opponent_player = Self::get_bid_nil_opponent_player(game, turn_trick_state);
        if let Some(player_id) = opponent_player {
            let player = &game.seats[player_id];
            if player.id == winning_turn_card.seat_id {
                //fix: 如果需要reachbid 这里也可以跟一张小牌 没必要跟大的 对家肯定会破0  跟大的对方破0 会更多的机会增加对方bag
                if turn_trick_state.team_bt_delta > 0 {
                    let has_add = Utils::compute_lower_rank_and_most_card_num(
                        &hand_pile_state,
                        card_weights,
                    );
                    if has_add {
                        return true
                    }
                }
                else{
                    if let Some(card) = Utils::get_highest_but_less_than_win_card(
                        winning_card,
                        &hand_pile_state.playable_pile,
                    ) {
                        CardWeight::add_card_x(card.get_number() as i16, &card, card_weights);
                        return true;
                    }
                }
            }
        }
        false
    }

    pub fn need_attack_nil_as_leader(
        game: &Round,
        hand_pile_state: &TurnHandPileState,
        turn_trick_state: &TurnState,
        card_weights: &mut Vec<CardWeight>,
    ) -> bool {
        let opponent_player = Self::get_bid_nil_opponent_player(game, turn_trick_state);
        if let Some(player_id) = opponent_player {
            let player = &game.seats[player_id];
            let mut flag = false;
            let player2 = if player.id == turn_trick_state.pre_player_id {
                &game.seats[turn_trick_state.pre_player_id]
            } else {
                &game.seats[turn_trick_state.next_player_id]
            };
            if !player.voided_suits.is_empty() {
                for item in hand_pile_state.playable_pile.iter() {
                    if !item.is_trump_card()
                        || hand_pile_state.playable_pile.len() == hand_pile_state.spades_pile.len()
                    {
                        let card_x = if !player.voided_suits.contains(&item.suit) {
                            100
                        } else {
                            0
                        };
                        CardWeight::add_card_x(card_x, &item, card_weights);
                    }
                }
            }
            if !player2.voided_suits.is_empty() && !player2.has_no_trump_card() {
                for item2 in hand_pile_state.playable_pile.iter() {
                    if !item2.is_trump_card()
                        || hand_pile_state.playable_pile.len() == hand_pile_state.spades_pile.len()
                    {
                        let pile = &hand_pile_state
                            .pile_suit_group
                            .get_suit_pocker_cards(item2.suit);
                        let history_pile = &turn_trick_state
                            .history_suit_piles
                            .get_suit_pocker_cards(item2.suit);
                        if let Some(card) = Utils::get_lowest_rank_card(pile) {
                            if Utils::get_greeter_rank_but_hidden_card_nums(
                                card,
                                pile,
                                history_pile,
                            ) > 0
                            {
                                flag = true;
                                let card_x2 = if player2.voided_suits.contains(&item2.suit) {
                                    50
                                } else {
                                    0
                                };
                                CardWeight::add_card_x(card_x2, item2, card_weights);
                                let card_x2 = 14 - item2.get_number() as i16;
                                CardWeight::add_card_y(card_x2, item2, card_weights);
                            }
                        }
                    }
                }
                if flag {
                    return true;
                }
            }
            let mut flag2 = true;
            if hand_pile_state.playable_pile.len() != hand_pile_state.spades_pile.len() {
                flag2 = !player.id == turn_trick_state.pre_player_id;
            }
            for item3 in hand_pile_state.playable_pile.iter() {
                let suit = item3.suit;
                if item3.is_trump_card() && !flag2 {
                    continue;
                }
                flag = true;
                let pile2 = &hand_pile_state.pile_suit_group.get_suit_pocker_cards(suit);
                let pile3 = &turn_trick_state
                    .history_suit_piles
                    .get_suit_pocker_cards(suit);

                if let Some(card) = Utils::get_lowest_rank_card(pile2) {
                    if pile3.len() == 0 {
                        for item4 in hand_pile_state.playable_pile.iter() {
                            if hand_pile_state.mid_cards.contains(&item4) {
                                CardWeight::add_card_x(10, item4, card_weights);
                            }
                        }
                    }
                    let card_y = if pile3.len() == 0 && item3 != card {
                        10
                    } else {
                        0
                    };
                    CardWeight::add_card_y(card_y, item3, card_weights);
                    let card_y =
                        Utils::get_greeter_rank_but_hidden_card_nums(item3, pile2, pile3) as i16;
                    CardWeight::add_card_z(card_y, item3, card_weights);
                }
            }
            if flag {
                return true;
            }
        }
        false
    }

    pub fn need_attack_nil_when_voided_suit(
        game: &Round,
        hand_pile_state: &TurnHandPileState,
        turn_trick_state: &TurnState,
        card_weights: &mut Vec<CardWeight>,
    ) -> bool {
        let cur_turn = game.cur_turn();
        let winning_turn_card = cur_turn.winning_card();
        let winning_card = &winning_turn_card.card;
        let leading_card = cur_turn.leading_card();
        let suit = leading_card.card.suit;

        let opponent_player = Self::get_bid_nil_opponent_player(game, turn_trick_state);
        if let Some(player_id) = opponent_player {
            let player = &game.seats[player_id];
            if player.is_suit_voided(suit)
                && winning_turn_card.seat_id != turn_trick_state.partner_player_id
            {
                if !winning_card.is_trump_card() && hand_pile_state.spades_pile.len() > 0 {
                    CardWeight::add_playable_spades_card_weight(hand_pile_state, card_weights);
                    return true;
                }
                if winning_card.is_trump_card() && hand_pile_state.spades_pile.len() > 0 {
                    if let Some(card) = Utils::get_lowest_but_greater_than_win_card(
                        winning_card,
                        &hand_pile_state.spades_pile,
                    ) {
                        CardWeight::add_card_x(card.get_number() as i16, &card, card_weights);
                        return true;
                    }
                }
            }
            if let Some(card2) = cur_turn.get_play_card_by_seat(player.id) {
                if (turn_trick_state.is_leading_partner
                    || turn_trick_state.is_leading_pre_player_id)
                    && hand_pile_state.spades_pile.len() > 0
                {
                    if leading_card.card.is_trump_card()
                        && card2.is_trump_card()
                        && winning_turn_card.seat_id != player.id
                    {
                        if let Some(card) =
                            Utils::get_highest_rank_from_pile(&hand_pile_state.spades_pile)
                        {
                            if card.get_number() > card2.get_number() {
                                CardWeight::add_card_x(
                                    card.get_number() as i16,
                                    &card,
                                    card_weights,
                                );
                                return true;
                            }
                        }
                    }
                }
            }

            if player.id == winning_turn_card.seat_id
                && hand_pile_state.spades_pile.len() > 0
                && hand_pile_state.playable_pile.len() != hand_pile_state.spades_pile.len()
            {
                let pile = &hand_pile_state.pile_suit_group.get_suit_pocker_cards(suit);
                let pile2 = &turn_trick_state
                    .history_suit_piles
                    .get_suit_pocker_cards(suit);
                let num = 13 - pile.len() as i8 - pile2.len() as i8;
                let num2 = Utils::get_greeter_rank_but_hidden_card_nums(winning_card, pile, pile2);
                let num3 = num2 as f32 / num as f32;
                if num3 <= 0.7 {
                    for item in hand_pile_state.playable_pile.iter() {
                        if !item.is_trump_card() {
                            let pile3 =
                                &hand_pile_state.pile_suit_group.get_suit_pocker_cards(suit);
                            let card_x = if pile3.len() == 1 { 10 } else { 0 };
                            CardWeight::add_card_x(card_x, item, card_weights);
                            let card_y = pile3.len() as i16;
                            CardWeight::add_card_y(card_y, item, card_weights);
                            let card_z = 14 - i16::abs(item.get_number() as i16 - 6);
                            CardWeight::add_card_z(card_z, item, card_weights);
                        }
                    }
                    return true;
                }
            }
        }
        false
    }
    /// ai 没有考虑同时bid nil的情况
    pub fn get_bid_nil_opponent_player(game: &Round, trick_state: &TurnState) -> Option<usize> {
        let player = &game.seats[trick_state.pre_player_id];
        if player.bid.unwrap() == 0 && player.tricks == 0 {
            return Some(player.id);
        }
        let player2 = &game.seats[trick_state.next_player_id];
        if player2.bid.unwrap() == 0 && player2.tricks == 0 {
            return Some(player2.id);
        }
        None
    }
}
